package com.emser.unc.server;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jdo.JDOCanRetryException;
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import org.datanucleus.store.appengine.query.JDOCursorHelper;

import com.emser.unc.serializable.ProductDTO;
import com.emser.unc.serializable.ResultDTO;
import com.emser.unc.serializable.SellerDTO;
import com.emser.unc.server.domain.Product;
import com.emser.unc.server.domain.ProductIndex;
import com.emser.unc.server.domain.ProductSold;
import com.emser.unc.server.domain.SaleReport;
import com.emser.unc.server.domain.SaleReportIndex;
import com.emser.unc.server.domain.Seller;
import com.emser.unc.server.domain.SellerProducts;
import com.emser.unc.server.domain.UserAccount;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class AppLibProduct {
	private static final int NUM_RETRIES = 5;
	
	public static boolean addProductDataStore(String userAName, ProductDTO productDTO) {	
		Product product = createProductDB(productDTO);
		PersistenceManager pm = PMF.get().getPersistenceManager();
	    Transaction tx = null;
	    UserAccount user = null;
	    Key k = KeyFactory.createKey(UserAccount.class.getSimpleName(),userAName);
	    try {
	      for (int i = 0; i < NUM_RETRIES; i++) {
	        tx = pm.currentTransaction();
	        tx.begin();
	        user = pm.getObjectById(UserAccount.class, k);
	        user.addProduct(product);
	        product.setCode();
	        try {
	          tx.commit();
	          break;
	        }
	        catch (JDOCanRetryException e1) {
	          if (i == (NUM_RETRIES - 1)) {
	            throw e1;
	          }
	        }
	      } 
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	    }
	    finally {
	      if (tx.isActive()) {
	        tx.rollback();
	      }
	      pm.close();
	    }
		return true;
	}
	
	@SuppressWarnings("unchecked")
	public static ResultDTO<ProductDTO> getProductsDataStore(String pageCursor, int range,String userAName) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
	    Transaction tx = null;
	    List<Product> productList = null;
		List<Product> productListCopy = null;
		ResultDTO<ProductDTO> result = null;
		Key userName = KeyFactory.createKey(UserAccount.class.getSimpleName(), userAName);
		Query q = pm.newQuery(Product.class);
		q.setFilter("userA == :userName");
		q.setOrdering("title asc");
		q.setRange(0, range);
		if (pageCursor != null) {
        	Cursor cursor = Cursor.fromWebSafeString(pageCursor);
        	Map<String, Object> extensionMap = new HashMap<String,Object>();
        	extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
        	q.setExtensions(extensionMap);
        }
	    try {
	      for (int i = 0; i < NUM_RETRIES; i++) {
	        tx = pm.currentTransaction();
	        tx.begin();
	        productList =(List<Product>) q.execute(userName);
	        if (productList.iterator().hasNext()) {
	        	productListCopy = (List<Product>)pm.detachCopyAll(productList);
		        Cursor cursor = JDOCursorHelper.getCursor(productList);
		        pageCursor = cursor.toWebSafeString();
	        }
	        else {
	        	pageCursor = null;
	        }
	        try {
	          tx.commit();
	          break;
	        }
	        catch (JDOCanRetryException e1) {
	          if (i == (NUM_RETRIES - 1)) {
	            throw e1;
	          }
	        }
	      }
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	      return null;
	    }
	    finally {
	      if (tx.isActive()) {
	        tx.rollback();
	      }
	      pm.close();
	    }
	    if(productListCopy != null){
	    	result = new ResultDTO<ProductDTO>();
	    	result.setList(toDTO(productListCopy));
	    	result.setCursorString(pageCursor);
        	return result;
	    }
	    else return null;
	}
	
	public static ArrayList<ProductDTO> getSellerProducts(SellerDTO seller){
		SellerProducts sellerProducts = getSellerProducts(seller.getUserName());
		if(sellerProducts != null){
			List<Product> products = AppLibProduct.getProducts(sellerProducts.getCodeProducts());
			if(products == null)
				return null;
			else
				return toDTO(products);
		}
		else return null;
	}
	
	public static ArrayList<ProductDTO> toDTO(List<Product> products){
		ArrayList<ProductDTO> productsDTO = new ArrayList<ProductDTO>();
        for(int i = 0;i<products.size();i++)
        	productsDTO.add(Product.toDTO(products.get(i)));
        return productsDTO;
	}
	
	@SuppressWarnings("unchecked")
	public static ResultDTO<ProductDTO> getSearchProducts(String pageCursor, int range,ArrayList<String> searchParam) {
		List<Product> products = null;
		ResultDTO<ProductDTO> result = null;
		List<Product> productsCopy = null;
		Key userKey = KeyFactory.createKey(UserAccount.class.getSimpleName(), searchParam.get(0));
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q = pm.newQuery(Product.class);
		if (searchParam.size()== 2){
			q.setFilter("title >= :1 && title < :2 && userA == :3");
			q.setOrdering("title asc");
			q.setRange(0, range);
			if (pageCursor != null) {
	        	Cursor cursor = Cursor.fromWebSafeString(pageCursor);
	        	Map<String, Object> extensionMap = new HashMap<String, Object>();
	        	extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
	        	q.setExtensions(extensionMap);
	        }
			products = (List<Product>) q.execute(searchParam.get(1)  , (searchParam.get(1) + "\ufffd"),userKey);
		}
		if (searchParam.size() == 3){
			q.declareParameters("String tit, Long cod,com.google.appengine.api.datastore.Key uName");
			q.setFilter("title == tit && code == cod && userA == uName");
			q.setOrdering("title asc");
			q.setRange(0, range);
			if (pageCursor != null) {
	        	Cursor cursor = Cursor.fromWebSafeString(pageCursor);
	        	Map<String, Object> extensionMap = new HashMap<String, Object>();
	        	extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
	        	q.setExtensions(extensionMap);
	        }
			Long code = Long.parseLong(searchParam.get(2));
	        Object[] parameters = new Object[]{ searchParam.get(1),code , userKey };
	        products = (List<Product>) q.executeWithArray(parameters);
	        
		}
		if(products != null){
        	productsCopy = (List<Product>)pm.detachCopyAll(products);
	        Cursor cursor = JDOCursorHelper.getCursor(products);
	        pageCursor = cursor.toWebSafeString();
	        result = new ResultDTO<ProductDTO>();
	        result.setCursorString(pageCursor);
			result.setList(toDTO(productsCopy));
        }
		q.closeAll();
		pm.close();
		return result;	
	}	
	
	@SuppressWarnings("unchecked")
	public static Integer getSearchedProductsCount(ArrayList<String> searchParam) {
		List<Product> products = null;
		Integer result = 0;
		Key userKey = KeyFactory.createKey(UserAccount.class.getSimpleName(), searchParam.get(0));
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q = pm.newQuery(Product.class);
		if (searchParam.size() == 2){
			q.setFilter("title >= :1 && title < :2 && userA == :3");
			q.setOrdering("title asc");
			products = (List<Product>) q.execute(searchParam.get(1)  , (searchParam.get(1) + "\ufffd"),userKey);
		}
		if (searchParam.size() == 3){
			q.declareParameters("String tit, Long cod,com.google.appengine.api.datastore.Key uName");
			q.setFilter("title == tit && code == cod && userA == uName");
			q.setOrdering("title asc");
			Long cod = Long.parseLong(searchParam.get(2));
	        Object[] parameters = new Object[]{ searchParam.get(1),cod , userKey };
	        products = (List<Product>) q.executeWithArray(parameters);    
		}
		if(products != null){
        	result = products.size();
        }
		q.closeAll();
		pm.close();
		return result;	
	}	
	
	public static boolean deleteProduct(String userAName,Product product){
		ProductIndex productIndex;
		boolean result = false;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		KeyFactory.Builder productIKeyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
    	productIKeyBuilder.addChild(Product.class.getSimpleName(), product.getCode()).addChild(ProductIndex.class.getSimpleName(), product.getCode());
    	Key productIndexKey = productIKeyBuilder.getKey();
    	KeyFactory.Builder keyBuilderProduct = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
    	keyBuilderProduct.addChild(Product.class.getSimpleName(), product.getCode());
    	Key productKey = keyBuilderProduct.getKey();
		Transaction tx = null;
		try{
			for (int i = 0; i < NUM_RETRIES; i++) {
		        tx = pm.currentTransaction();
		        tx.begin();
		        try{
		        	productIndex = pm.getObjectById(ProductIndex.class, productIndexKey);
		        	Set<String> sellersUNames = productIndex.getUserNameSellers();
		        	Iterator<String> itsellerUName = sellersUNames.iterator();
		        	while(itsellerUName.hasNext()){
		        		String sellerUName = itsellerUName.next();	
		        		KeyFactory.Builder sellerPKeyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
		            	sellerPKeyBuilder.addChild(Seller.class.getSimpleName(), sellerUName).addChild(SellerProducts.class.getSimpleName(), sellerUName);
		            	Key sellerProductsKey = sellerPKeyBuilder.getKey();
		            	KeyFactory.Builder sellerKeyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
		            	sellerKeyBuilder.addChild(Seller.class.getSimpleName(), sellerUName);
		            	Key sellerKey = sellerKeyBuilder.getKey();
		        		SellerProducts sellerProducts = pm.getObjectById(SellerProducts.class,sellerProductsKey);
		        		sellerProducts.getCodeProducts().remove(product.getCode());
		        		Seller seller = pm.getObjectById(Seller.class, sellerKey);
		        		seller.setVersionProduct(seller.getVersionProduct()+new Long(1));
		        		if(sellerProducts.getCodeProducts().isEmpty())
		        			sellerProducts.setCodeProducts(new ArrayList<Long>());	
		        		pm.makePersistent(sellerProducts);
		        	}
		        	pm.deletePersistent(productIndex);
		        	
		        }catch(javax.jdo.JDOObjectNotFoundException e){}
		        	try{	
		        		Product p = (Product) pm.getObjectById(Product.class,productKey);
          				pm.deletePersistent(p);
          				result = true;
		        	}catch(Exception e){}
		        	
		        try {
			         tx.commit();			         
			         break;
			    }
			    catch (JDOCanRetryException e1) {
			         if (i == (NUM_RETRIES - 1)) {
			           throw e1;
			         }
			    }
		      }
		}
		catch (Exception e) {
			result = false;
			e.printStackTrace();
		}
		finally {
			if (tx.isActive()) {
			   tx.rollback();
			}
			pm.close();
		}
		return result;
	}
	
	public static boolean deleteProductsDataStore(String userAName, ArrayList<Long> productsCodes) {
		boolean result = false;
	    List<Product> products = null;
	    products = getProducts(productsCodes);
	    if(products != null){
	    	result = true;
	    	Iterator<Product> iterator= products.iterator();
	    	while((iterator.hasNext())&&(result)){
	    		Product product = iterator.next();
	    		result = deleteProduct(userAName,product);
	    	}
	    }
        return result;
	}
	
	@SuppressWarnings("unchecked")
	public static Integer getProductsCount(String userAName){
		PersistenceManager pm = PMF.get().getPersistenceManager();
	    Transaction tx = null;
	    Integer productCount = 0;
	    List<Product> productList = new ArrayList<Product>();
		List<Product> result = new ArrayList<Product>();
		Key userKey = KeyFactory.createKey(UserAccount.class.getSimpleName(), userAName);
	    Query q = pm.newQuery(Product.class);
	    q.setFilter("userA == :userName");
		try {
	      for (int i = 0; i < NUM_RETRIES; i++) {
	        tx = pm.currentTransaction();
	        tx.begin();
	        productList =(List<Product>) q.execute(userKey); 
	        result = (List<Product>)pm.detachCopyAll(productList);
	        if(result != null && !result.isEmpty())
	        	productCount = result.size();
	        try {
	          tx.commit();
	          break;
	        }
	        catch (JDOCanRetryException e1) {
	          if (i == (NUM_RETRIES - 1)) {
	            throw e1;
	          }
	        }
	      } 
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	    }
	    finally {
	      if (tx.isActive()) {
	        tx.rollback();
	      }
	      pm.close();
	    }	
		return productCount;	
	}
	
	public static boolean deletePSellerReferences(String userAName,String sellerUName,List<Long> productsCodes){
		ProductIndex productIndex = null;
		boolean result = false;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Iterator<Long> itproduct = productsCodes.iterator();	
		Transaction tx = null;
		try {
		      for (int i = 0; i < NUM_RETRIES; i++) {
		        tx = pm.currentTransaction();
		        tx.begin();
		        while(itproduct.hasNext()){
		        	Long productCode = itproduct.next();
		        	KeyFactory.Builder productIKeyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
		        	productIKeyBuilder.addChild(Product.class.getSimpleName(), productCode).addChild(ProductIndex.class.getSimpleName(), productCode);
		        	Key productIndexKey = productIKeyBuilder.getKey();
		        	try{						
		        		productIndex = pm.getObjectById(ProductIndex.class, productIndexKey);
		        	}catch(javax.jdo.JDOObjectNotFoundException e){
		        		productIndex = null;
		        	}
		        	if(productIndex != null){
		        		productIndex.getUserNameSellers().remove(sellerUName);
		        		if(productIndex.getUserNameSellers().isEmpty())
		        			pm.deletePersistent(productIndex);
		        	}
		        }
		        try {
			         tx.commit();
			         result = true;
			         break;
			    }
			    catch (JDOCanRetryException e1) {
			         if (i == (NUM_RETRIES - 1)) {
			           throw e1;
			         }
			    }
		      }
		}
		catch (Exception e) {
			result = false;
			e.printStackTrace();
		}
		finally {
			if (tx.isActive()) {
			   tx.rollback();
			}
			pm.close();
		}
		return result;
		      
	}
	public static SellerProducts getSellerProducts(String sellerUName){
		SellerProducts sellerProducts = null, sellerProductsCopy = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q = pm.newQuery(SellerProducts.class,"sellerKey == :sellerKey");
		q.setUnique(true);
		try{
			sellerProducts = (SellerProducts) q.execute(sellerUName);
			sellerProductsCopy = (SellerProducts) pm.detachCopy(sellerProducts);
		}
		catch(Exception e){
			e.printStackTrace();
		}
		finally{
			q.closeAll();
			pm.close();
		}
		return sellerProductsCopy;
		
	}
	
	public static boolean updateProductDataStore(String userAName, ProductDTO productDTO) {
		boolean result= false;
		Product product = null;
		ProductIndex productIndex = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();
	    Transaction tx = null;
	    KeyFactory.Builder productIkeyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
		productIkeyBuilder.addChild(Product.class.getSimpleName(), productDTO.getCode()).addChild(ProductIndex.class.getSimpleName(), productDTO.getCode());
		Key productIndexKey = productIkeyBuilder.getKey();
	    Query q = pm.newQuery(Product.class, "code == :codeParam");
		q.setUnique(true);
	    try {
	      for (int i = 0; i < NUM_RETRIES; i++) {
	        tx = pm.currentTransaction();
	        tx.begin();
	        product = (Product) q.execute(productDTO.getCode());
			product.setStock(productDTO.getStock());
			product.setTitle(productDTO.getTitle());
			product.setUnitPrice(productDTO.getUnitPrice());
			try{
				productIndex = pm.getObjectById(ProductIndex.class, productIndexKey);
	      	}catch(javax.jdo.JDOObjectNotFoundException e){
				productIndex = null;
			}
	      	if (productIndex != null) {
				Iterator<String> it = productIndex.getUserNameSellers().iterator();
				while(it.hasNext()){
					String sellerUName = it.next();
					KeyFactory.Builder keyBuilderTwo = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
					keyBuilderTwo.addChild(Seller.class.getSimpleName(), sellerUName);
					Key sellerKey = keyBuilderTwo.getKey();
					Seller seller = pm.getObjectById(Seller.class, sellerKey);
					seller.setVersionProduct(seller.getVersionProduct()+new Long(1));
					pm.makePersistent(seller);
				}
			}
	        try {
	          tx.commit();
	          result = true;
	          break;
	        }
	        catch (JDOCanRetryException e1) {
	          if (i == (NUM_RETRIES - 1)) {
	            throw e1;
	          }
	        }
	      } 
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	    }
	    finally {
	      if (tx.isActive()) {
	        tx.rollback();
	      }
	      q.closeAll();
	      pm.close();
	    }
		return result;
	}
	public static boolean addProductsSeller(ArrayList<Long> productsCodes,String sellerUName,String userAName){
		Seller seller = null;
		boolean result = true;
		SellerProducts sellerProducts = null;
		Iterator<Long> iterator= productsCodes.iterator();
		Transaction tx = null;
		ProductIndex productIndex = null;
		seller = AppLibSeller.getSeller(sellerUName);
		sellerProducts = getSellerProducts(sellerUName);
		if(sellerProducts == null){
			KeyFactory.Builder sellerPKeyBuilderOne = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
	    	sellerPKeyBuilderOne.addChild(Seller.class.getSimpleName(), sellerUName).addChild(SellerProducts.class.getSimpleName(), sellerUName);
	    	Key sellerProductsKey = sellerPKeyBuilderOne.getKey();
	    	sellerProducts = new SellerProducts(sellerProductsKey,sellerUName);
		}
		if(!sellerProducts.getCodeProducts().isEmpty()){
			result = deletePSellerReferences(userAName,sellerUName,sellerProducts.getCodeProducts());
			sellerProducts.getCodeProducts().clear();
		}
		if(result){
			PersistenceManager pm = PMF.get().getPersistenceManager();
			seller.setVersionProduct(seller.getVersionProduct() + new Long(1));
			sellerProducts.setCodeProducts(new ArrayList<Long>());
			try {
			      for (int i = 0; i < NUM_RETRIES; i++) {
			        tx = pm.currentTransaction();
			        tx.begin();
			        while(iterator.hasNext()){
			        	Long codeProduct = iterator.next();
			        	sellerProducts.getCodeProducts().add(codeProduct);
			        	KeyFactory.Builder keyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
			        	keyBuilder.addChild(Product.class.getSimpleName(), codeProduct).addChild(ProductIndex.class.getSimpleName(), codeProduct);
			        	Key ckey = keyBuilder.getKey();
			        	try{
			        		productIndex = pm.getObjectById(ProductIndex.class, ckey);
			        	}catch(javax.jdo.JDOObjectNotFoundException e){
			        		productIndex = null;
			        	}
			        	if (productIndex == null) {
			        		productIndex = new ProductIndex(sellerUName, ckey);
			        		pm.makePersistent(productIndex);
			        	}
			        	else{
			        		productIndex.addSellerKey(sellerUName);
			        		pm.makePersistent(productIndex);
			        	}
			        }
			        pm.makePersistent(seller);
			        pm.makePersistent(sellerProducts);
			        try {
				         tx.commit();
				         break;
				    }
				    catch (JDOCanRetryException e1) {
				         if (i == (NUM_RETRIES - 1)) {
				           throw e1;
				         }
				    }
			      }
			}
			catch (Exception e) {
				e.printStackTrace();
				return false;
			}
			finally {
				if (tx.isActive()) {
				   tx.rollback();
				}
				pm.close();
			}
		}	
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public static boolean updateStock(String userAName,Date updateDate){
		UserAccount user = null;
		boolean result = false;
		SaleReportIndex sReportI = null;
		ProductSold pS = null;
		List<Key> saleReportsKeys = null, keys;
		List<SaleReportIndex> saleReportsIndexs = null;
		Iterator<Key> itReportsKeys;
		Iterator<SaleReportIndex> it;
		Iterator<ProductSold> itPSold;
		Map<Long,Long> map = new HashMap<Long,Long>(); 
		Transaction tx = null;
		Key userName = KeyFactory.createKey(UserAccount.class.getSimpleName(), userAName);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q = pm.newQuery("select key from " + SaleReport.class.getName()+" where userAName == :userA && date > :updateLastDate");
		Query q2 = pm.newQuery("select from " + SaleReportIndex.class.getName()+" where key == :keys");
		keys = new ArrayList<Key>();
		try {
	    	for (int i = 0; i < NUM_RETRIES; i++) {
	    		tx = pm.currentTransaction();
	    		tx.begin();
	    		user = (UserAccount) pm.getObjectById(UserAccount.class, userName);
	    		saleReportsKeys = (List<Key>) q.execute(userAName, user.getStockUpdateLastDate());
	    		if((!saleReportsKeys.isEmpty())&&(saleReportsKeys != null)){
	    			itReportsKeys = saleReportsKeys.iterator();
	    			while(itReportsKeys.hasNext()){
	    				Key reportKeytemp = itReportsKeys.next();
	    				KeyFactory.Builder reportIKeyBuilder = new KeyFactory.Builder(UserAccount.class.getSimpleName(), userAName);
	    				reportIKeyBuilder.addChild(SaleReport.class.getSimpleName(), reportKeytemp.getId()).addChild(SaleReportIndex.class.getSimpleName(), reportKeytemp.getId());
	    				Key reportKey = reportIKeyBuilder.getKey();
	    				keys.add(reportKey);    			
	    			}
	    			saleReportsIndexs = (List<SaleReportIndex>)q2.execute(keys);
	    		}	    			
	    			try {
	    				tx.commit();
	    				if(saleReportsIndexs != null){
	    					it = saleReportsIndexs.iterator();
	    					while(it.hasNext()){
	    						sReportI = it.next();
	    						itPSold = sReportI.getProductsS().iterator();
	    						while(itPSold.hasNext()){
	    							pS = itPSold.next();
	    							if(!map.containsKey(pS.getIdProduct())){
	    								map.put(pS.getIdProduct(), pS.getQuantity());
	    							}else{
	    								Long newQuantity = pS.getQuantity() + map.get(pS.getIdProduct());
	    								map.put(pS.getIdProduct(), newQuantity);
	    							}		
	    						}	
	    					}
	    					result = true;
	    				}
	    			break;
	    		}
	    		catch (JDOCanRetryException e1) {
	    			if (i == (NUM_RETRIES - 1)) {
	    				throw e1;
	    			}
	    		}
	    	}
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	      return false;
	    }
	    finally {
	      if (tx.isActive()) {
	        tx.rollback();
	      }
	      pm.close();
	    }
	    if(result)
	    	return updateProductsStock(map, userAName, updateDate);
	    else return false;
		
	}
	
	@SuppressWarnings("unchecked")
	public static boolean updateProductsStock(Map<Long,Long> map,String userAName,Date updateDate){
		Transaction tx = null;
		boolean result = false;
		List<Long> codes = null;
		UserAccount user = null;
		List<Product> products = null;
		Iterator<Product> itProducts;
		Key userKey = KeyFactory.createKey(UserAccount.class.getSimpleName(), userAName);
		if(!map.isEmpty()){
			Iterator<Map.Entry<Long, Long>> it = map.entrySet().iterator();
			codes = new ArrayList<Long>();
			while(it.hasNext()){
				Map.Entry<Long, Long> e = (Map.Entry<Long, Long>) it.next();
				codes.add(e.getKey());
			}
	    	PersistenceManager pm = PMF.get().getPersistenceManager();
			Query q = pm.newQuery(Product.class);
		    q.setFilter("code == :codes && userA == :userName");
	    	try {
	    		for (int i = 0; i < NUM_RETRIES; i++) {
	    			tx = pm.currentTransaction();
	    			tx.begin();
	    			products = (List<Product>) q.execute(codes, userAName);
	    			itProducts = products.iterator();
	    			while(itProducts.hasNext()){
	    				Product product = itProducts.next();
	    				product.setStock(product.getStock() - map.get(product.getCode()));
	    			}
	    			user = (UserAccount) pm.getObjectById(UserAccount.class, userKey);
	    			user.setStockUpdateLastDate(updateDate);
	    			result = true;
	    			try {
	    				tx.commit();
	    				break;
	    			}
	    			catch (JDOCanRetryException e1) {
	    				if (i == (NUM_RETRIES - 1)) {
	    					throw e1;
	    				}
	    			}
	    		}
	    	}
	    		catch (Exception e) {
	    		e.printStackTrace();
	    		result = false;
	    	}
	    	finally {
	    		if (tx.isActive()) {
	    			tx.rollback();
	    		}	    		
	    		pm.close();
	    	}
	    }
	    return result;
	}
	
	@SuppressWarnings("unchecked")
	public static List<Product> getProducts(List<Long> productsCodes){
		List<Product> products = null;
		List<Product> result = null;
		if(productsCodes.isEmpty()||productsCodes == null)
			return result;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q = pm.newQuery("select from " +Product.class.getName()+" where code == :keys");//order by title asc
		try{
			products = (List<Product>)q.execute(productsCodes);
			result = (List<Product>)pm.detachCopyAll(products);
		}catch(Exception e){
			e.printStackTrace();
		}
		finally{
			pm.close();
			q.closeAll();
		}
		return result; 
		
	}
	
	public static List<Long> getProductsCode(String sellerUName) {
		List<Long> result;
		SellerProducts sellerProducts = getSellerProducts(sellerUName);
		if(sellerProducts == null)
			result = new ArrayList<Long>();
		else
			result = sellerProducts.getCodeProducts();
		return result;	
	}
	
	public static Product createProductDB(ProductDTO productDTO){
		Product product = new Product();
		product.setTitle(productDTO.getTitle());
		product.setUnitPrice(productDTO.getUnitPrice());
		product.setStock(productDTO.getStock());
		return product;
	}

	public static Date getLastUpdateDate(String userAName) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = null;
		UserAccount user = null;
		Date date = null;
		Key userKey = KeyFactory.createKey(UserAccount.class.getSimpleName(), userAName);
		try {
		      for (int i = 0; i < NUM_RETRIES; i++) {
		        tx = pm.currentTransaction();
		        tx.begin();
		        user = (UserAccount) pm.getObjectById(UserAccount.class,userKey);
		        if (user != null) {
		          date = user.getStockUpdateLastDate();
		        }
		        try {
		          tx.commit();
		          break;
		        }
		        catch (JDOCanRetryException e1) {
		          if (i == (NUM_RETRIES - 1)) {
		            throw e1;
		          }
		        }
		      } 
		 }
		 catch (JDOException e) {
		      e.printStackTrace();
		      return null;
		 }
		 finally {
		      if (tx.isActive()) {
		        tx.rollback();
		      }
		      pm.close();
		 }
		return date;
	}
}
